﻿using FunArts.EasyDevOps.Shared.Models.SshClient;
using FunArts.EasyDevOps.Shared.Models.SshWebSocket.Enums;
using FunArts.EasyDevOps.Shared.Models.SshWebSocket.Request;
using FunArts.EasyDevOps.Shared.Models.SshWebSocket.Response;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.WebSockets;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

namespace FunArts.EasyDevOps.Rcl.Service.Impl
{
    public class SshWebSocketClient
    {
        private readonly ClientWebSocket _webSocket;

        public SshWebSocketClient(string webSocketUrl)
        {
            _webSocket = new ClientWebSocket();
            _webSocket.ConnectAsync(new Uri(webSocketUrl), CancellationToken.None).Wait();
        }

        public async Task<string> SendRequestAsync<T>(SshWebSocketRequestTypeEnum type, T request)
        {
            var socketRequest = new SshWebSocketRequest<T>
            {
                Type = type,
                SshRequest=request
            };

            var requestJson = JsonSerializer.Serialize(socketRequest);
            var buffer = Encoding.UTF8.GetBytes(requestJson);

            await _webSocket.SendAsync(new ArraySegment<byte>(buffer), WebSocketMessageType.Text, true, CancellationToken.None);

            var responseBuffer = new byte[1024 * 4];
            var result = await _webSocket.ReceiveAsync(new ArraySegment<byte>(responseBuffer), CancellationToken.None);
            return Encoding.UTF8.GetString(responseBuffer, 0, result.Count);
        }

        public async Task<DirectoryNode> LoadDirectoryTree(DirectoryNode node)
        {
            LoadDirectoryTreeRequest request = new LoadDirectoryTreeRequest() { DirectoryNode = node };
            
            var response = await SendRequestAsync(SshWebSocketRequestTypeEnum.LoadDirectoryTree, request);
            var result = JsonSerializer.Deserialize<SshWebSocketResponse<LoadDirectoryTreeResponse>>(response);

            if (!result.Success)
            {
                throw new Exception(result.Error);
            }

            if (result.SshResponse.DirectoryNode!= null)
            {
                return result.SshResponse.DirectoryNode;
            }
            else
            {
               return node;
            }
        }
    }
}
